様々な情報タイプを検出・マスキングできるGoogle CloudのDLP APIをAWS Lambdaから使ってみた
はじめに
こんにちは、筧( @TakaakiKakei )です。
ChatGPT API への質問前に、質問内の機密データを検出してマスキング処理したいと思っていたところ、 Google Cloud の Data Loss Prevention API(以降、(DLP API) に出会いました。
DLP API は、クレジットカード番号、氏名といった情報タイプを、すばやく見つけて保護するのに役に立ちます。 今回は個人的に使い慣れている AWS Lambda から DLP API を使ってみます。
前提
検出可能な情報タイプは以下のページを参照ください。 検出可能な情報タイプは150種類以上用意されています。 またページ内の記載の通り、100% 正確に検出できるわけではないので予めご了承ください。
infoType 検出器リファレンス | データ損失防止(DLP)のドキュメント | Google Cloud
Cloud Data Loss Preventionでは、情報タイプ(infoType)を使用してスキャンする対象を定義します。infoType は、名前、メールアドレス、電話番号、識別番号、クレジット カード番号などの機密データのタイプを表します。
..snip..
重要: 組み込みの infoType 検出器は、100% 正確な検出方法ではありません。たとえば、この検出器によって法令要件の遵守を保証することはできません。どのデータが機密であるか、それを保護する最善の方法は何かを決めるのは、お客様の責任です。構成が要件を確実に満たしているかどうか、設定内容を検証することをおすすめします。
やってみた
コード
Serverless Framework を利用してデプロイします。デプロイ方法はREADMEを参照ください。
ポイント
info_typesの選択
DLP API では、info_types(検出する情報タイプ)を選択できます。 リクエストあたりの infoType の最大数は150という制限があるので超えないようにしましょう。
def mask_text(dlp_client: DlpServiceClient, project_id: str, text: str) -> str: ..snip.. selected_info_types = [ "PERSON_NAME", "EMAIL_ADDRESS", "AWS_CREDENTIALS", ..snip..
機密性の高いデータ用の組み込み infoType 検出器の一覧が公式ドキュメントで紹介されているので、こちらもよかったら参照ください。
min_likelihoodの選択
DLP API では、min_likelihood(一致の可能性)で、取得するスキャン結果の可能性の最小レベルを設定できます。 前述のコード内では、POSSIBLEにしましたが、それぞれテストをしてみて要件に合うものを選択しましょう。
def mask_text(dlp_client: DlpServiceClient, project_id: str, text: str) -> str: ..snip.. info_types = [{"name": info_type} for info_type in selected_info_types] inspect_config = { "info_types": info_types, "min_likelihood": "POSSIBLE", }
- LIKELIHOOD_UNSPECIFIED デフォルト値。POSSIBLE と同じです。
- VERY_UNLIKELY データが特定の InfoType に一致する可能性が非常に低いことを表します。
- UNLIKELY データが特定の InfoType に一致する可能性が低いことを表します。
- POSSIBLE データが特定の InfoType に一致する可能性があることを表します。
- LIKELY データが特定の InfoType に一致する可能性が高いことを表します。
- VERY_LIKELY データが特定の InfoType に一致する可能性が非常に高いことを表します。
一致の可能性 | データ損失防止(DLP)のドキュメント | Google Cloud
外部モジュールの読み込み
はじめは poetry を利用していましたが、AWS Lambda実行時に、Runtime.ImportModuleError
が発生してしまいました。
具体的には、cannot import name 'cygrpc' from 'grpc._cython'
というエラーです。
根本解決はできていませんが、pipenv を利用することで回避できました。
pipenv の利用に切り替えたので、外部モジュールの読み込みには、dockerizePip: true
を利用しました。
custom: pythonRequirements: dockerizePip: true zip: true slim: true layer: true
動かしてみる
devステージでデプロイしていると、blog-lambda-dlp-api-dev というステートマシンができています。 こちらを使って実行してみます。
名前
{ "text": "私の名前は筧 剛彰です。" }
名前をマスキングできました!
メールアドレス
{ "text": "メールアドレスは、taro.yamada@example.comです" }
うまくマスキングされなかったので、min_likelihood を UNLIKELY に調整して実行します。
def mask_text(dlp_client: DlpServiceClient, project_id: str, text: str) -> str: ..snip.. info_types = [{"name": info_type} for info_type in selected_info_types] inspect_config = { "info_types": info_types, "min_likelihood": "UNLIKELY", }
マスキングされましたが、メールアドレスの後の文字列もマスキングされてしまいました。
min_likelihood を POSSIBLE に戻して、入力例のメールアドレスの前後に余白を入れてみます。
def mask_text(dlp_client: DlpServiceClient, project_id: str, text: str) -> str: ..snip.. info_types = [{"name": info_type} for info_type in selected_info_types] inspect_config = { "info_types": info_types, "min_likelihood": "POSSIBLE", }
{ "text": "メールアドレスは、taro.yamada@example.com です" }
メールアドレスのみマスキングすることができました! このように info_type に指定したものが必ずしも想定通りに動作するわけではありません。
意図した動作に近づけていくには、min_likelihood の調整, 入力を info_type に検出されやすいように事前加工、カスタム infoType の利用などが考えられます。
おわりに
最後まで読んでいただきありがとうございます。
この記事が皆さんのお役に立てたば幸いです。
それではまた!